using System;
using System.Linq;
using System.Reflection;
using Synapse.Framework.AoP.Attributes.Core;

namespace Synapse.Framework.AoP
{
    public class InterceptorBuilder : IInterceptorBuilder
    {
        private readonly IResolver resolver;
        private IInterceptor interceptor;

        public InterceptorBuilder(IResolver resolver)
        {
            this.resolver = resolver;
            interceptor = new NullInterceptor();
        }
       
        private class NullInterceptor : IInterceptor
        {
            public void Intercept(IInvocation invocation)
            {
                invocation.InvokeMethod();
            }
        }

        public IInterceptorBuilder Define(MethodInfo methodInfo)
        {
            var interceptorMethodAttribute =
                methodInfo.GetCustomAttributes(typeof (InterceptorMethodAttribute), false).SingleOrDefault() as
                InterceptorMethodAttribute;
            if (interceptorMethodAttribute == null) 
                return this;
            var interceptorMethod = resolver.Resolve(interceptorMethodAttribute.Type()) as IInterceptor;
            if (interceptorMethod != null)
                interceptor  = interceptorMethod;
            return this;
        }

        public void Intercept(IInvocation invocation)
        {
            interceptor.Intercept(invocation);
        }

        public IInterceptorBuilder Define(Type type)
        {
            var interceptorClassAttribute =
                type.GetCustomAttributes(typeof(InterceptorClassAttribute), false).SingleOrDefault() as
                InterceptorClassAttribute;
            if (interceptorClassAttribute == null)
                return this;
            var interceptorClass = resolver.Resolve(interceptorClassAttribute.Type()) as IInterceptor;
            if (interceptorClass != null)
                interceptor = interceptorClass;
            return this;
        }
    }
}